package mips.instructions;

import mips.Main;

/**
 * <code>JAL</code> instruction<br/>
 * Jump And Link<br/>
 * @author jnmartin84@gmail.com
 */
public class JAL extends Instruction {

	private static final JAL INSTANCE = new JAL();
	private static final String INSTRUCTION_NAME = "JAL";

	private JAL(){}

	public static final JAL getInstance() {
		return INSTANCE;
	}

	/**
	 * <b>Format:</b><br/>
	 * JAL target<br/><br/>
	 * <b>Description:</b><br/>
	 * The 26-bit target address is shifted left two bits and combined with the<br/>
	 * high-order bits of the address of the delay slot. The program<br/>
	 * unconditionally jumps to this calculated address with a delay of one<br/>
	 * instruction. The address of the instruction after the delay slot is placed in<br/>
	 * the link register, r31.<br/><br/>
	 * <b>Operation:</b><br/>
	 * T: temp &larr; target<br/>
	 * GPR[31] &larr; PC + 8<br/>
	 * T+1: PC &larr; PC<sub>31&hellip;28</sub> || temp || 0<sup>2</sup>
	 */
	@Override
	public final void execute(final int instruction) {
		
		final int target = (instruction & 0x03FFFFFF) << 2;

		mips.R4300i.GPR[31] = mips.R4300i.PC + 8;
		
		mips.R4300i.PC = mips.R4300i.nPC;
		mips.R4300i.nPC = (mips.R4300i.nPC & 0xF0000000) | target;

		if(Main.tracing) {
			
			mips.R4300i.targets.put(mips.R4300i.nPC,null);
		}
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final String emit(final int instruction) {
		
		final int target = (instruction & 0x03FFFFFF) << 2;

		return 	"		mips.CPU.GPR[31] = mips.CPU.PC + 8;\n" +
				"		\n" +
				"		mips.CPU.PC = mips.CPU.nPC;\n" + 
				"		mips.CPU.nPC = (mips.CPU.nPC & 0xF0000000) | "+String.format("0x%08X",target)+";\n";
	}
	 
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final String getName(final int instruction) {
		return getName();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public final String getName() {
		return INSTRUCTION_NAME;
	}
}